/*============================================================================
*  FILE: SafetyBeltModel.c
*=============================================================================
* Copyright  2025 Shanghai Hongqu Automobile Technology Co., LTD. 
* All rights reserved.
* Confidential - Restricted Shanghai Hongqu Automobile Technology Co., LTD. 
* Do not disclose.
*-----------------------------------------------------------------------------
*
*  DESCRIPTION:
*  	 Telltale Safety Belt Model Logic
*
*
*===========================================================================*/

#include "SafetyBeltModel.h"
#include "audio_service_api.h"
#include "Common/DataStructureMacro.h"
#include "ssas_api.h"
//TODO
//#include "ssas_api.h"

#define LOG_TAG "TT"
#include "log_api.h"


/*----------------------------------------------------------------------
状态    常亮                        长灭                        紧急状态
条件    自检                        报文故障                    ON档车速>10,未系安全带
条件    ACC档未系安全带              ACC档已系安全带
条件    ON档车速<10,未系安全带       ON档车速<10,已系安全带
条件                                ON档车速>10,已系安全带
条件                                OFF档

常亮:灯常亮
长灭:灯常灭
紧急状态:闪烁90s，后常亮，播放报警音90s
----------------------------------------------------------------------*/

#define SBL_AUDIO_ID AUDIO_1

#define SAFETYBELT_SELFCHECK_COUNT 3 //
#define SAFETYBELT_EMERGENCY_SPEED 10 //start blink speed 10 km
#define SAFETYBELT_BLINK_COUNT 5 //1hz 0.5s blink
#define SAFETYBELT_BLINK_TIMEOUT 180 //90s timeout

static void SafetyBeltGetEvent(SafetyBeltWorkingData* workData)
{
    uint16_t rawDataDriver;
    uint16_t rawDataPassenger;
    uint16_t rawData;

    //TODO signal timeout should treat as off
    if (Com_ReceiveSignal(COM_SID_DrSbltAtc, &rawDataDriver) != E_OK)    
    {
        workData->driverEvent = EV_Unknown;
    }
    else
    {
        if (rawData == 0)
            workData->driverEvent = EV_On;
        else if (rawData == 1)
            workData->driverEvent = EV_Off;
        else
            workData->driverEvent = EV_Unknown;
    }

    //TODO signal timeout should treat as off
    if (Com_ReceiveSignal(COM_SID_PassSbltAtc, &rawDataPassenger) != E_OK)    
    {
        workData->passengerEvent = EV_Unknown;
    }
    else
    {
        if (rawData == 0)
            workData->passengerEvent = EV_On;
        else if (rawData == 1)
            workData->passengerEvent = EV_Off;
        else
            workData->passengerEvent = EV_Unknown;
    }
}

static void SafetyBeltBlink(SafetyBeltWorkingData* workData)
{
    // in emergency state
    if (workData->currentState == State_Emergency)
    {
        if (workData->blinkTimeout < SAFETYBELT_BLINK_TIMEOUT)
        {
            workData->blinkCount++;
            workData->blinkTimeout++;
        }

        if (workData->blinkTimeout >= SAFETYBELT_BLINK_TIMEOUT)
        {
            if (workData->driverEvent == EV_On)
                workData->driverBlinkState = Blink_On;

            if (workData->passengerEvent == EV_On)
                workData->passengerBlinkState = Blink_On;

            workData->blinkCount = 0;
            workData->blinkTimeout = 0;
        }
        else if (workData->blinkCount >= SAFETYBELT_BLINK_COUNT)
        {
            if (workData->driverEvent == EV_On)
                workData->driverBlinkState = (workData->driverBlinkState == Blink_Off) ? Blink_On : Blink_Off;

            if (workData->passengerEvent == EV_On)
                workData->passengerBlinkState = (workData->passengerBlinkState == Blink_Off) ? Blink_On : Blink_Off;

            workData->blinkCount = 0;
        }
    }
    // all telltale off
    else if (workData->currentState == State_Init)
    {
        workData->blinkCount = 0;
        workData->blinkTimeout = 0;
        workData->driverBlinkState = Blink_Off;
        workData->passengerBlinkState = Blink_Off;
    }
}

static void SafetyBeltStateTransition(SafetyBeltWorkingData* workData)
{
    uint16_t displaySpeed = getDisplaySpeed();
    uint16_t accState = getAccState();

    // acc off
    if (accState == ACC_OFF)
    {
        // TODO stop audio playback
        workData->driverBlinkState = Blink_Off;
        workData->passengerBlinkState = Blink_Off;
        workData->currentState = State_Init;
    }
    // acc on
    else if (accState == ACC_ON)
    {
        switch (workData->currentState)
        {
            case State_Init:
            {
                if (accState == ACC_ON)
                {
                    workData->driverBlinkState = Blink_On;
                    workData->passengerBlinkState = Blink_On;
                    workData->blinkCount = 0;
                    workData->currentState = State_Selfcheck;
                }
            }
            break;
            case State_Selfcheck:
            {
                workData->blinkCount++;

                if (workData->blinkCount >= SAFETYBELT_SELFCHECK_COUNT)
                {
                    workData->blinkCount = 0;

                    if (workData->driverEvent == EV_Off)
                    { 
                        workData->driverBlinkState = Blink_Off;
                    }
                    if (workData->passengerEvent == EV_On)
                    {
                        workData->passengerBlinkState = Blink_Off;
                    }

                    if ((workData->driverEvent == EV_On) || (workData->passengerEvent == EV_On))
                    {
                        if (displaySpeed >= SAFETYBELT_EMERGENCY_SPEED)
                        {
                            //audio playback
                            workData->currentState = State_Emergency;
                        }
                        else
                        {
                            workData->currentState = State_On;
                        }
                    }
                    else
                    {
                        workData->currentState = State_Off;
                    }                
                }
            }
            break;            
            case State_Off:
                if ((workData->driverEvent == EV_On) || (workData->passengerEvent == EV_On))
                {
                    if (workData->driverEvent == EV_On)
                    { 
                        workData->driverBlinkState = Blink_On;
                    }
                    if (workData->passengerEvent == EV_On)
                    {
                        workData->passengerBlinkState = Blink_On;
                    }

                    if (displaySpeed >= SAFETYBELT_EMERGENCY_SPEED)
                    {
                        //audio playback
                        workData->currentState = State_Emergency;
                    }
                    else
                        workData->currentState = State_On;
                }
            break;

            case State_On:
                if (workData->driverEvent == EV_Off)
                { 
                    workData->driverBlinkState = Blink_Off;
                }
                if (workData->passengerEvent == EV_Off)
                {
                    workData->passengerBlinkState = Blink_Off;
                }

                if ((workData->driverEvent == EV_Off) && (workData->passengerEvent == EV_Off))
                {
                    workData->currentState = State_Off;
                }
                else if (displaySpeed >= SAFETYBELT_EMERGENCY_SPEED)
                {
                    //audio playback
                    workData->currentState = State_Emergency;
                }
            break;

            case State_Emergency:
                if (workData->driverEvent == EV_Off)
                { 
                    workData->driverBlinkState = Blink_Off;
                }
                if (workData->passengerEvent == EV_Off)
                {
                    workData->passengerBlinkState = Blink_Off;
                }

                if ((workData->driverEvent == EV_Off) && (workData->passengerEvent == EV_Off))
                {
                    // stop audio playback
                    workData->currentState = State_Off;
                }
                else if (displaySpeed < SAFETYBELT_EMERGENCY_SPEED)
                {
                    // stop audio playback
                    workData->currentState = State_On;
                }
            break;
            default:
            break;
        }
    }
}

static void init()
{
    SafetyBeltWorkingDataInstance.driverBlinkState = State_Init;
    SafetyBeltWorkingDataInstance.passengerBlinkState = State_Init;
    SafetyBeltWorkingDataInstance.driverEvent = EV_Unknown;
    SafetyBeltWorkingDataInstance.passengerEvent = EV_Unknown;
    SafetyBeltWorkingDataInstance.blinkCount = 0;
    SafetyBeltWorkingDataInstance.blinkTimeout = 0;
    SafetyBeltWorkingDataInstance.hasDriverWidget = false;
    SafetyBeltWorkingDataInstance.hasPassangerWidget = false;
}

static void run()
{
    //get event
    SafetyBeltGetEvent(&SafetyBeltWorkingDataInstance);
    //state transition
    SafetyBeltStateTransition(&SafetyBeltWorkingDataInstance);
    //blink
    SafetyBeltBlink(&SafetyBeltWorkingDataInstance);
}

static void release()
{

}

SafetyBeltModel g_SafetyBeltModelInstance = {
    {
        init,
        run,
        release,
        MIN_PERIOD,
    },
};

// ----------------------------------View------------------------------

